<script setup lang="ts">
import { ref, onMounted } from 'vue'
import MVT from 'ol/format/MVT.js'
import Map from 'ol/Map.js'
import TileGrid from 'ol/tilegrid/TileGrid.js'
import VectorTileLayer from 'ol/layer/VectorTile.js'
import VectorTileSource from 'ol/source/VectorTile.js'
import View from 'ol/View.js'
import { get as getProjection } from 'ol/proj.js'
import { Style, Fill, Icon, Stroke, Text } from 'ol/style.js'

let map
const key = 'pk.eyJ1IjoiYWhvY2V2YXIiLCJhIjoiY2t0cGdwMHVnMGdlbzMxbDhwazBic2xrNSJ9.WbcTL9uj8JPAsnT9mgb7oQ'
// Calculation of resolutions that match zoom levels 1, 3, 5, 7, 9, 11, 13, 15.
const resolutions = []
for (let i = 0; i <= 8; ++i) {
  resolutions.push(156543.03392804097 / Math.pow(2, i * 2))
}

const mapViewer = ref<HTMLDivElement>()

onMounted(() => {
  map = new Map({
    layers: [
      new VectorTileLayer({
        source: new VectorTileSource({
          attributions:
            '© <a href="https://www.mapbox.com/map-feedback/">Mapbox</a> ' +
            '© <a href="https://www.openstreetmap.org/copyright">' +
            'OpenStreetMap contributors</a>',
          format: new MVT(),
          tileGrid: new TileGrid({
            extent: getProjection('EPSG:3857')?.getExtent(),
            resolutions,
            tileSize: 512
          }),
          tileUrlFunction
        }),
        style: createMapboxStreetsV6Style(Style, Fill, Stroke, Icon, Text)
      })
    ],
    target: mapViewer.value,
    view: new View({
      center: [0, 0],
      minZoom: 1,
      zoom: 2
    })
  })
})

// Calculation of tile urls for zoom levels 1, 3, 5, 7, 9, 11, 13, 15.
function tileUrlFunction(tileCoord) {
  return (
    'https://{a-d}.tiles.mapbox.com/v4/mapbox.mapbox-streets-v6/' +
    '{z}/{x}/{y}.vector.pbf?access_token=' +
    key
  )
    .replace('{z}', String(tileCoord[0] * 2 - 1))
    .replace('{x}', String(tileCoord[1]))
    .replace('{y}', String(tileCoord[2]))
    .replace('{a-d}', 'abcd'.substr(((tileCoord[1] << tileCoord[0]) + tileCoord[2]) % 4, 1))
}

function createMapboxStreetsV6Style(e, t, o, a, r) {
  var l = new t({ color: '' }),
    s = new o({ color: '', width: 1 }),
    n = new e({ fill: l }),
    i = new e({ fill: l, stroke: s }),
    d = new e({ stroke: s }),
    g = new e({ text: new r({ text: '', fill: l, stroke: s }) }),
    c = {}
  function b(t) {
    var o = c[t]
    return (
      o ||
        ((o = new e({
          image: new a({
            src: 'https://cdn.jsdelivr.net/npm/@mapbox/maki@4.0.0/icons/' + t + '-15.svg',
            imgSize: [15, 15],
            crossOrigin: 'anonymous'
          })
        })),
        (c[t] = o)),
      o
    )
  }
  var m = []
  return function (e, t) {
    var o = 0,
      a = e.get('layer'),
      r = e.get('class'),
      c = e.get('type'),
      C = e.get('scalerank'),
      x = e.get('labelrank'),
      h = e.get('admin_level'),
      p = e.get('maritime'),
      _ = e.get('disputed'),
      T = e.get('maki'),
      W = e.getGeometry().getType()
    return (
      'landuse' == a && 'park' == r
        ? (l.setColor('#d8e8c8'), (m[o++] = n))
        : 'landuse' == a && 'cemetery' == r
        ? (l.setColor('#e0e4dd'), (m[o++] = n))
        : 'landuse' == a && 'hospital' == r
        ? (l.setColor('#fde'), (m[o++] = n))
        : 'landuse' == a && 'school' == r
        ? (l.setColor('#f0e8f8'), (m[o++] = n))
        : 'landuse' == a && 'wood' == r
        ? (l.setColor('rgb(233,238,223)'), (m[o++] = n))
        : ('waterway' == a && 'river' != r && 'stream' != r && 'canal' != r) ||
          ('waterway' == a && 'river' == r)
        ? (s.setColor('#a0c8f0'), s.setWidth(1), (m[o++] = d))
        : 'waterway' != a || ('stream' != r && 'canal' != r)
        ? 'water' == a
          ? (l.setColor('#a0c8f0'), (m[o++] = n))
          : 'aeroway' == a && 'Polygon' == W
          ? (l.setColor('rgb(242,239,235)'), (m[o++] = n))
          : 'aeroway' == a && 'LineString' == W && t <= 76.43702828517625
          ? (s.setColor('#f0ede9'), s.setWidth(1), (m[o++] = d))
          : 'building' == a
          ? (l.setColor('#f2eae2'), s.setColor('#dfdbd7'), s.setWidth(1), (m[o++] = i))
          : 'tunnel' == a && 'motorway_link' == r
          ? (s.setColor('#e9ac77'), s.setWidth(1), (m[o++] = d))
          : 'tunnel' == a && 'service' == r
          ? (s.setColor('#cfcdca'), s.setWidth(1), (m[o++] = d))
          : 'tunnel' != a || ('street' != r && 'street_limited' != r)
          ? ('tunnel' == a && 'main' == r && t <= 1222.99245256282) ||
            ('tunnel' == a && 'motorway' == r)
            ? (s.setColor('#e9ac77'), s.setWidth(1), (m[o++] = d))
            : 'tunnel' == a && 'path' == r
            ? (s.setColor('#cba'), s.setWidth(1), (m[o++] = d))
            : 'tunnel' == a && 'major_rail' == r
            ? (s.setColor('#bbb'), s.setWidth(2), (m[o++] = d))
            : 'road' == a && 'motorway_link' == r
            ? (s.setColor('#e9ac77'), s.setWidth(1), (m[o++] = d))
            : 'road' != a || ('street' != r && 'street_limited' != r) || 'LineString' != W
            ? ('road' == a && 'main' == r && t <= 1222.99245256282) ||
              ('road' == a && 'motorway' == r && t <= 4891.96981025128)
              ? (s.setColor('#e9ac77'), s.setWidth(1), (m[o++] = d))
              : 'road' == a && 'path' == r
              ? (s.setColor('#cba'), s.setWidth(1), (m[o++] = d))
              : 'road' == a && 'major_rail' == r
              ? (s.setColor('#bbb'), s.setWidth(2), (m[o++] = d))
              : ('bridge' == a && 'motorway_link' == r) || ('bridge' == a && 'motorway' == r)
              ? (s.setColor('#e9ac77'), s.setWidth(1), (m[o++] = d))
              : 'bridge' == a && 'service' == r
              ? (s.setColor('#cfcdca'), s.setWidth(1), (m[o++] = d))
              : 'bridge' != a || ('street' != r && 'street_limited' != r)
              ? 'bridge' == a && 'main' == r && t <= 1222.99245256282
                ? (s.setColor('#e9ac77'), s.setWidth(1), (m[o++] = d))
                : 'bridge' == a && 'path' == r
                ? (s.setColor('#cba'), s.setWidth(1), (m[o++] = d))
                : 'bridge' == a && 'major_rail' == r
                ? (s.setColor('#bbb'), s.setWidth(2), (m[o++] = d))
                : ('admin' == a && h >= 3 && 0 === p) ||
                  ('admin' == a && 2 == h && 0 === _ && 0 === p) ||
                  ('admin' == a && 2 == h && 1 === _ && 0 === p)
                ? (s.setColor('#9e9cab'), s.setWidth(1), (m[o++] = d))
                : ('admin' == a && h >= 3 && 1 === p) || ('admin' == a && 2 == h && 1 === p)
                ? (s.setColor('#a0c8f0'), s.setWidth(1), (m[o++] = d))
                : 'country_label' == a && 1 === C
                ? (g.getText().setText(e.get('name_en')),
                  g.getText().setFont('bold 11px "Open Sans", "Arial Unicode MS"'),
                  l.setColor('#334'),
                  s.setColor('rgba(255,255,255,0.8)'),
                  s.setWidth(2),
                  (m[o++] = g))
                : 'country_label' == a && 2 === C && t <= 19567.87924100512
                ? (g.getText().setText(e.get('name_en')),
                  g.getText().setFont('bold 10px "Open Sans", "Arial Unicode MS"'),
                  l.setColor('#334'),
                  s.setColor('rgba(255,255,255,0.8)'),
                  s.setWidth(2),
                  (m[o++] = g))
                : 'country_label' == a && 3 === C && t <= 9783.93962050256
                ? (g.getText().setText(e.get('name_en')),
                  g.getText().setFont('bold 9px "Open Sans", "Arial Unicode MS"'),
                  l.setColor('#334'),
                  s.setColor('rgba(255,255,255,0.8)'),
                  s.setWidth(2),
                  (m[o++] = g))
                : 'country_label' == a && 4 === C && t <= 4891.96981025128
                ? (g.getText().setText(e.get('name_en')),
                  g.getText().setFont('bold 8px "Open Sans", "Arial Unicode MS"'),
                  l.setColor('#334'),
                  s.setColor('rgba(255,255,255,0.8)'),
                  s.setWidth(2),
                  (m[o++] = g))
                : ('marine_label' == a && 1 === x && 'Point' == W) ||
                  ('marine_label' == a && 2 === x && 'Point' == W)
                ? (g.getText().setText(e.get('name_en')),
                  g.getText().setFont('italic 11px "Open Sans", "Arial Unicode MS"'),
                  l.setColor('#74aee9'),
                  s.setColor('rgba(255,255,255,0.8)'),
                  s.setWidth(1),
                  (m[o++] = g))
                : 'marine_label' == a && 3 === x && 'Point' == W
                ? (g.getText().setText(e.get('name_en')),
                  g.getText().setFont('italic 10px "Open Sans", "Arial Unicode MS"'),
                  l.setColor('#74aee9'),
                  s.setColor('rgba(255,255,255,0.8)'),
                  s.setWidth(1),
                  (m[o++] = g))
                : 'marine_label' == a && 4 === x && 'Point' == W
                ? (g.getText().setText(e.get('name_en')),
                  g.getText().setFont('italic 9px "Open Sans", "Arial Unicode MS"'),
                  l.setColor('#74aee9'),
                  s.setColor('rgba(255,255,255,0.8)'),
                  s.setWidth(1),
                  (m[o++] = g))
                : 'place_label' == a && 'city' == c && t <= 1222.99245256282
                ? (g.getText().setText(e.get('name_en')),
                  g.getText().setFont('11px "Open Sans", "Arial Unicode MS"'),
                  l.setColor('#333'),
                  s.setColor('rgba(255,255,255,0.8)'),
                  s.setWidth(1),
                  (m[o++] = g))
                : 'place_label' == a && 'town' == c && t <= 305.748113140705
                ? (g.getText().setText(e.get('name_en')),
                  g.getText().setFont('9px "Open Sans", "Arial Unicode MS"'),
                  l.setColor('#333'),
                  s.setColor('rgba(255,255,255,0.8)'),
                  s.setWidth(1),
                  (m[o++] = g))
                : 'place_label' == a && 'village' == c && t <= 38.21851414258813
                ? (g.getText().setText(e.get('name_en')),
                  g.getText().setFont('8px "Open Sans", "Arial Unicode MS"'),
                  l.setColor('#333'),
                  s.setColor('rgba(255,255,255,0.8)'),
                  s.setWidth(1),
                  (m[o++] = g))
                : 'place_label' == a &&
                  t <= 19.109257071294063 &&
                  ('hamlet' == c || 'suburb' == c || 'neighbourhood' == c)
                ? (g.getText().setText(e.get('name_en')),
                  g.getText().setFont('bold 9px "Arial Narrow"'),
                  l.setColor('#633'),
                  s.setColor('rgba(255,255,255,0.8)'),
                  s.setWidth(1),
                  (m[o++] = g))
                : (('poi_label' == a && t <= 19.109257071294063 && 1 == C && 'marker' !== T) ||
                    ('poi_label' == a && t <= 9.554628535647032 && 2 == C && 'marker' !== T) ||
                    ('poi_label' == a && t <= 4.777314267823516 && 3 == C && 'marker' !== T) ||
                    ('poi_label' == a && t <= 2.388657133911758 && 4 == C && 'marker' !== T) ||
                    ('poi_label' == a && t <= 1.194328566955879 && C >= 5 && 'marker' !== T)) &&
                  (m[o++] = b(T))
              : (s.setColor('#cfcdca'), s.setWidth(1), (m[o++] = d))
            : (s.setColor('#cfcdca'), s.setWidth(1), (m[o++] = d))
          : (s.setColor('#cfcdca'), s.setWidth(1), (m[o++] = d))
        : (s.setColor('#a0c8f0'), s.setWidth(1), (m[o++] = d)),
      (m.length = o),
      m
    )
  }
}
</script>

<template>
  <div ref="mapViewer" class="map"></div>
</template>

<style lang="less" scoped>
.map {
  width: 100%;
  height: 100%;
  background: #f8f4f0;
  &:focus {
    outline: #4a74a8 solid 0.15em;
  }
}
</style>
